import { App } from 'vue'

// 是否为开发环境
const DEV_MODE = process.env.NODE_ENV !== 'production'

// 全局 app 配置插件
export default {
  install(app: App) {
    console.info(`>>>>>> 当前 Vue 版本：${app.version} >>>>>>`)
    /**
     * @description 应用内未捕获错误全局处理 它可以从下面这些来源中捕获错误：
     组件渲染器 | 事件处理器 | 生命周期钩子 | setup() 函数 | 侦听器 | 自定义指令钩子 | 过渡 (Transition) 钩子
     * @param err 错误对象
     * @param instance 触发错误的组件实例
     * @param info 错误信息
     */
    app.config.errorHandler = (err, instance, info) => {
      if (!DEV_MODE) return
      console.group('>>>>>> 错误对象 Error >>>>>>')
      console.log(err)
      console.groupEnd()
      console.group('>>>>>> Vue 组件实例 >>>>>>')
      console.log(instance)
      console.groupEnd()
      console.group('>>>>>> 错误信息 Info >>>>>>')
      console.log(info)
      console.groupEnd()
    }

    // 设置此项为 true 可以在浏览器开发工具的“性能/时间线”页中启用对组件初始化、编译、渲染和修补的性能表现追踪。仅在开发模式和支持 performance.mark API 的浏览器中工作。
    app.config.performance = DEV_MODE

    // 将所有标签前缀为 `ion-` 的标签视为自定义元素
    // app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ion-')

    // 用于调整是否移除模板中的 HTML 注释。
    // app.config.compilerOptions.comments = !DEV_MODE

    // app.config.globalProperties 一个用于注册能够被应用内所有组件实例访问到的全局属性的对象。
    // 这是对 Vue 2 中 Vue.prototype 使用方式的一种替代，此写法在 Vue 3 已经不存在了。与任何全局的东西一样，应该谨慎使用。
    // 如果全局属性与组件自己的属性冲突，组件自己的属性将具有更高的优先级。
    /**
     * 获取屏幕宽高 兼容性处理
     * return {width: 100, height: 100}
     */
    app.config.globalProperties.$getScreen = (): {
      width: number
      height: number
    } => {
      let width
      let height
      if (window.innerWidth || window.innerHeight) {
        width = window.innerWidth
        height = window.innerHeight
      } else if (document.compatMode === 'BackCompat') {
        width = document.body.clientWidth
        height = document.body.clientHeight
      } else {
        width = document.documentElement.clientWidth
        height = document.documentElement.clientHeight
      }
      return {
        width,
        height
      }
    }
    /**
     * 获取元素样式 兼容性处理
     * @param dom 元素
     * @param name 属性
     * return 500px
     */
    app.config.globalProperties.$getStyleAttr = (dom: any, name: any): string => {
      if (dom.currentStyle) {
        return dom.currentStyle[name]
      } else {
        return getComputedStyle(dom)[name]
      }
    }
    /**
     * 获取页面滚动坐标值 兼容性处理
     * return {x: 100, y: 100}
     */
    app.config.globalProperties.$getPageScroll = (): {
      x: number
      y: number
    } => {
      let x
      let y
      if (window.pageXOffset || window.pageYOffset) {
        x = window.pageXOffset
        y = window.pageYOffset
      } else if (document.compatMode === 'BackCompat') {
        x = document.body.scrollLeft
        y = document.body.scrollTop
      } else {
        x = document.documentElement.scrollLeft
        y = document.documentElement.scrollTop
      }
      return {
        x,
        y
      }
    }
    // 函数防抖 - 输入框
    app.config.globalProperties.$debounce = function (fn: any, delay: number): any {
      // fn = test
      let timerId: number | null | undefined = null
      return (...args: any) => {
        timerId && clearTimeout(timerId)
        timerId = window.setTimeout(() => {
          fn.apply(this, args)
        }, delay || 1000)
      }
    }
    // 函数节流 - onscroll/onresize
    app.config.globalProperties.$throttle = function (fn: any, delay: number): any {
      // fn = test
      let timerId: number | null | undefined = null
      let flag = true
      return (...args: any) => {
        if (!flag) {
          return
        }
        flag = false
        timerId && clearTimeout(timerId)
        timerId = window.setTimeout(() => {
          flag = true
          fn.apply(this, args)
        }, delay || 1000)
      }
    }
  }
}
